/* Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * Assignment
 */
'use strict'

angular.module('flowableModeler').controller('FlowableAssignmentCtrl', [
  '$scope',
  '$modal',
  function ($scope, $modal) {
    // Config for the modal window
    var opts = {
      template: 'editor-app/configuration/properties/assignment-popup.html?version=' + Date.now(),
      scope: $scope
    }

    // Open the dialog
    _internalCreateModal(opts, $modal, $scope)
  }
])

angular.module('flowableModeler').controller('FlowableAssignmentPopupCtrl', [
  '$rootScope',
  '$scope',
  '$translate',
  '$http',
  '$timeout',
  'UserService',
  'GroupService',
  function ($rootScope, $scope, $translate, $http, $timeout, UserService, GroupService) {
    // Put json representing assignment on scope
    if (
      $scope.property.value !== undefined &&
      $scope.property.value !== null &&
      $scope.property.value.assignment !== undefined &&
      $scope.property.value.assignment !== null
    ) {
      $scope.assignment = $scope.property.value.assignment
      if (typeof $scope.assignment.type === 'undefined') {
        $scope.assignment.type = 'static'
      }
    } else {
      $scope.assignment = { type: 'idm' }
    }

    $scope.popup = {
      assignmentObject: {
        type: $scope.assignment.type,
        idm: {
          type: undefined,
          assignee: undefined,
          candidateUsers: [],
          candidateGroups: []
        },
        static: {
          assignee: undefined,
          candidateUsers: [],
          candidateGroups: []
        }
      }
    }

    $scope.assignmentOptions = [
      { id: 'initiator', title: $translate.instant('PROPERTY.ASSIGNMENT.IDM.DROPDOWN.INITIATOR') },
      { id: 'user', title: $translate.instant('PROPERTY.ASSIGNMENT.IDM.DROPDOWN.USER') },
      { id: 'reportTo', title: $translate.instant('PROPERTY.ASSIGNMENT.IDM.DROPDOWN.REPORTTO') },
      { id: 'thirdParty', title: $translate.instant('PROPERTY.ASSIGNMENT.IDM.DROPDOWN.THIRDPARTY') },
      { id: 'users', title: $translate.instant('PROPERTY.ASSIGNMENT.IDM.DROPDOWN.USERS') },
      { id: 'groups', title: $translate.instant('PROPERTY.ASSIGNMENT.IDM.DROPDOWN.GROUPS') }
    ]

    if ($scope.assignment.idm && $scope.assignment.idm.type) {
      for (var i = 0; i < $scope.assignmentOptions.length; i++) {
        if ($scope.assignmentOptions[i].id == $scope.assignment.idm.type) {
          $scope.assignmentOption = $scope.assignmentOptions[i]
          break
        }
      }
    }

    // fill the IDM area
    if (!$scope.assignmentOption) {
      // Default, first time opening the popup
      $scope.assignmentOption = $scope.assignmentOptions[0]
    } else {
      // Values already filled
      if ($scope.assignment.idm) {
        //fill the IDM tab
        if ($scope.assignment.idm.assignee) {
          if ($scope.assignment.idm.assignee.id) {
            $scope.popup.assignmentObject.idm.assignee = $scope.assignment.idm.assignee
          } else {
            $scope.popup.assignmentObject.idm.assignee = { email: $scope.assignment.idm.assignee.email }
          }
        }

        if ($scope.assignment.idm.candidateUsers && $scope.assignment.idm.candidateUsers.length > 0) {
          for (var i = 0; i < $scope.assignment.idm.candidateUsers.length; i++) {
            $scope.popup.assignmentObject.idm.candidateUsers.push($scope.assignment.idm.candidateUsers[i])
          }
        }

        if ($scope.assignment.idm.candidateGroups && $scope.assignment.idm.candidateGroups.length > 0) {
          for (var i = 0; i < $scope.assignment.idm.candidateGroups.length; i++) {
            $scope.popup.assignmentObject.idm.candidateGroups.push($scope.assignment.idm.candidateGroups[i])
          }
        }
      }
    }

    //fill the static area
    if ($scope.assignment.assignee) {
      $scope.popup.assignmentObject.static.assignee = $scope.assignment.assignee
    }

    if ($scope.assignment.candidateUsers && $scope.assignment.candidateUsers.length > 0) {
      for (var i = 0; i < $scope.assignment.candidateUsers.length; i++) {
        $scope.popup.assignmentObject.static.candidateUsers.push($scope.assignment.candidateUsers[i])
      }
    }

    if ($scope.assignment.candidateGroups && $scope.assignment.candidateGroups.length > 0) {
      for (var i = 0; i < $scope.assignment.candidateGroups.length; i++) {
        $scope.popup.assignmentObject.static.candidateGroups.push($scope.assignment.candidateGroups[i])
      }
    }

    initStaticContextForEditing($scope)

    $scope.$watch('popup.groupFilter', function () {
      $scope.updateGroupFilter()
    })

    $scope.$watch('popup.filter', function () {
      $scope.updateFilter()
    })

    $scope.updateFilter = function () {
      if ($scope.popup.oldFilter == undefined || $scope.popup.oldFilter != $scope.popup.filter) {
        if (!$scope.popup.filter) {
          $scope.popup.oldFilter = ''
        } else {
          $scope.popup.oldFilter = $scope.popup.filter
        }

        if ($scope.popup.filter !== null && $scope.popup.filter !== undefined) {
          UserService.getFilteredUsersCRC($scope.popup.filter).then(function (result) {
            var filteredUsers = []
            for (var i = 0; i < result.records.length; i++) {
              var filteredUser = result.records[i]

              var foundCandidateUser = false
              if (
                $scope.popup.assignmentObject.idm.candidateUsers !== null &&
                $scope.popup.assignmentObject.idm.candidateUsers !== undefined
              ) {
                for (var j = 0; j < $scope.popup.assignmentObject.idm.candidateUsers.length; j++) {
                  var candidateUser = $scope.popup.assignmentObject.idm.candidateUsers[j]
                  if (candidateUser.id === filteredUser.id) {
                    foundCandidateUser = true
                    break
                  }
                }
              }

              if (!foundCandidateUser) {
                filteredUsers.push(filteredUser)
              }
            }

            $scope.popup.userResults = filteredUsers
            $scope.resetSelection()
          })
        }
      }
    }

    $scope.updateGroupFilter = function () {
      if ($scope.popup.oldGroupFilter == undefined || $scope.popup.oldGroupFilter != $scope.popup.groupFilter) {
        if (!$scope.popup.groupFilter) {
          $scope.popup.oldGroupFilter = ''
        } else {
          $scope.popup.oldGroupFilter = $scope.popup.groupFilter
        }

        if ($scope.popup.groupFilter !== null && $scope.popup.groupFilter !== undefined) {
          GroupService.getFilteredGroups($scope.popup.groupFilter).then(function (result) {
            $scope.popup.groupResults = result.data.list
            $scope.resetGroupSelection()
          })
        }
      }
    }

    $scope.confirmUser = function (user) {
      if (!user) {
        // Selection is done with keyboard, use selection index
        var users = $scope.popup.userResults
        if ($scope.popup.selectedIndex >= 0 && $scope.popup.selectedIndex < users.length) {
          user = users[$scope.popup.selectedIndex]
        }
      }

      if (user) {
        if ('user' == $scope.assignmentOption.id) {
          $scope.popup.assignmentObject.idm.assignee = user
        } else if ('users' == $scope.assignmentOption.id) {
          // Only add if not yet part of candidate users
          var found = false
          if ($scope.popup.assignmentObject.idm.candidateUsers) {
            for (var i = 0; i < $scope.popup.assignmentObject.idm.candidateUsers.length; i++) {
              if ($scope.popup.assignmentObject.idm.candidateUsers[i].id === user.id) {
                found = true
                break
              }
            }
          }

          if (!found) {
            $scope.addCandidateUser(user)
          }
        }
      }
    }

    $scope.confirmEmail = function () {
      if ('user' == $scope.assignmentOption.id) {
        $scope.popup.assignmentObject.idm.assignee = { email: $scope.popup.email }
      } else if ('users' == $scope.assignmentOption.id) {
        // Only add if not yet part of candidate users
        var found = false
        if ($scope.popup.assignmentObject.idm.candidateUsers) {
          for (var i = 0; i < $scope.popup.assignmentObject.idm.candidateUsers.length; i++) {
            if ($scope.popup.assignmentObject.idm.candidateUsers[i].id) {
              if ($scope.popup.assignmentObject.idm.candidateUsers[i].id === user.id) {
                found = true
                break
              }
            } else if ($scope.popup.assignmentObject.idm.candidateUsers[i].email) {
              if ($scope.popup.assignmentObject.idm.candidateUsers[i].email === $scope.popup.email) {
                found = true
                break
              }
            }
          }
        }

        if (!found) {
          $scope.addCandidateUser({ email: $scope.popup.email })
        }
      }
    }

    $scope.confirmGroup = function (group) {
      if (!group) {
        // Selection is done with keyboard, use selection index
        var groups = $scope.popup.groupResults
        if ($scope.popup.selectedGroupIndex >= 0 && $scope.popup.selectedGroupIndex < groups.length) {
          group = groups[$scope.popup.selectedGroupIndex]
        }
      }

      if (group) {
        // Only add if not yet part of candidate groups
        var found = false
        if ($scope.popup.assignmentObject.idm.candidateGroups) {
          for (var i = 0; i < $scope.popup.assignmentObject.idm.candidateGroups.length; i++) {
            if ($scope.popup.assignmentObject.idm.candidateGroups[i].id === group.id) {
              found = true
              break
            }
          }
        }

        if (!found) {
          $scope.addCandidateGroup(group)
        }
      }
    }

    $scope.addCandidateUser = function (user) {
      $scope.popup.assignmentObject.idm.candidateUsers.push(user)
    }

    $scope.removeCandidateUser = function (user) {
      var users = $scope.popup.assignmentObject.idm.candidateUsers
      var indexToRemove = -1
      for (var i = 0; i < users.length; i++) {
        if (user.id) {
          if (user.id === users[i].id) {
            indexToRemove = i
            break
          }
        } else {
          if (user.email === users[i].email) {
            indexToRemove = i
            break
          }
        }
      }
      if (indexToRemove >= 0) {
        users.splice(indexToRemove, 1)
      }
    }

    $scope.addCandidateGroup = function (group) {
      $scope.popup.assignmentObject.idm.candidateGroups.push(group)
    }

    $scope.removeCandidateGroup = function (group) {
      var groups = $scope.popup.assignmentObject.idm.candidateGroups
      var indexToRemove = -1
      for (var i = 0; i < groups.length; i++) {
        if (group.id == groups[i].id) {
          indexToRemove = i
          break
        }
      }
      if (indexToRemove >= 0) {
        groups.splice(indexToRemove, 1)
      }
    }

    $scope.resetSelection = function () {
      if ($scope.popup.userResults && $scope.popup.userResults.length > 0) {
        $scope.popup.selectedIndex = 0
      } else {
        $scope.popup.selectedIndex = -1
      }
    }

    $scope.nextUser = function () {
      var users = $scope.popup.userResults
      if (users && users.length > 0 && $scope.popup.selectedIndex < users.length - 1) {
        $scope.popup.selectedIndex += 1
      }
    }

    $scope.previousUser = function () {
      var users = $scope.popup.userResults
      if (users && users.length > 0 && $scope.popup.selectedIndex > 0) {
        $scope.popup.selectedIndex -= 1
      }
    }

    $scope.resetGroupSelection = function () {
      if ($scope.popup.groupResults && $scope.popup.groupResults.length > 0) {
        $scope.popup.selectedGroupIndex = 0
      } else {
        $scope.popup.selectedGroupIndex = -1
      }
    }

    $scope.nextGroup = function () {
      var groups = $scope.popup.groupResults
      if (groups && groups.length > 0 && $scope.popup.selectedGroupIndex < groups.length - 1) {
        $scope.popup.selectedGroupIndex += 1
      }
    }

    $scope.previousGroup = function () {
      var groups = $scope.popup.groupResults
      if (groups && groups.length > 0 && $scope.popup.selectedGroupIndex > 0) {
        $scope.popup.selectedGroupIndex -= 1
      }
    }

    $scope.removeAssignee = function () {
      $scope.popup.assignmentObject.idm.assignee = undefined
    }

    // Click handler for + button after enum value
    $scope.addCandidateUserValue = function (index) {
      $scope.popup.assignmentObject.static.candidateUsers.splice(index + 1, 0, { value: '' })
    }

    // Click handler for - button after enum value
    $scope.removeCandidateUserValue = function (index) {
      $scope.popup.assignmentObject.static.candidateUsers.splice(index, 1)
    }

    // Click handler for + button after enum value
    $scope.addCandidateGroupValue = function (index) {
      $scope.popup.assignmentObject.static.candidateGroups.splice(index + 1, 0, { value: '' })
    }

    // Click handler for - button after enum value
    $scope.removeCandidateGroupValue = function (index) {
      $scope.popup.assignmentObject.static.candidateGroups.splice(index, 1)
    }

    $scope.setSearchType = function () {
      $scope.popup.assignmentObject.assignmentSourceType = 'search'
    }

    $scope.allSteps = EDITOR.UTIL.collectSortedElementsFromPrecedingElements($scope.selectedShape)

    $scope.save = function () {
      var assignmentObject = $scope.popup.assignmentObject.static
      handleAssignmentInput($scope.popup.assignmentObject.static)

      $scope.assignment.type = $scope.popup.assignmentObject.type

      if ('idm' === $scope.popup.assignmentObject.type) {
        // IDM
        $scope.popup.assignmentObject.static = undefined

        //Construct an IDM object to be saved to the process model.
        var idm = { type: $scope.assignmentOption.id }
        if ('user' == idm.type) {
          if ($scope.popup.assignmentObject.idm.assignee) {
            idm.assignee = $scope.popup.assignmentObject.idm.assignee
          }
        } else if ('reportTo' == idm.type) {
          idm.assignee = { id: 'reportTo', userName: $translate.instant('PROPERTY.ASSIGNMENT.IDM.DROPDOWN.LEADER') }
        } else if ('users' == idm.type) {
          if (
            $scope.popup.assignmentObject.idm.candidateUsers &&
            $scope.popup.assignmentObject.idm.candidateUsers.length > 0
          ) {
            idm.candidateUsers = $scope.popup.assignmentObject.idm.candidateUsers
          }
        } else if ('groups' == idm.type) {
          if (
            $scope.popup.assignmentObject.idm.candidateGroups &&
            $scope.popup.assignmentObject.idm.candidateGroups.length > 0
          ) {
            idm.candidateGroups = $scope.popup.assignmentObject.idm.candidateGroups
          }
        } else if ('thirdParty' == idm.type) {
          var assignee = $scope.popup.assignmentObject.idm.assignee || {}
          var url = assignee.url
          var urlReg = /^(https?|ftp|file):\/\/[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]$/
          if (!url) {
            $scope.popup.assignmentObject.static = assignmentObject
            $rootScope.alerts['current'] = {
              type: 'alert-danger',
              message: $translate.instant('PROPERTY.ASSIGNMENT.THIRDPARTY-MESSAGE')
            }
            $timeout(function () {
              $rootScope.alerts['current'] = ''
            }, 3000)
            return
          } else if (!urlReg.test(url)) {
            $scope.popup.assignmentObject.static = assignmentObject
            $rootScope.alerts['current'] = {
              type: 'alert-danger',
              message: $translate.instant('PROPERTY.ASSIGNMENT.THIRDPARTY-URL-TEST')
            }
            $timeout(function () {
              $rootScope.alerts['current'] = ''
            }, 3000)
            return
          } else {
            idm.assignee = {
              id: 'thirdParty',
              userName: $translate.instant('PROPERTY.ASSIGNMENT.IDM.DROPDOWN.THIRDPARTY'),
              url: url
            }
          }
        }
        $scope.assignment.idm = idm
        $scope.assignment.assignee = undefined
        $scope.assignment.candidateUsers = undefined
        $scope.assignment.candidateGroups = undefined
      }

      if ('static' === $scope.popup.assignmentObject.type) {
        // IDM
        $scope.popup.assignmentObject.idm = undefined
        $scope.assignment.idm = undefined
        $scope.assignment.assignee = $scope.popup.assignmentObject.static.assignee
        $scope.assignment.candidateUsers = $scope.popup.assignmentObject.static.candidateUsers
        $scope.assignment.candidateGroups = $scope.popup.assignmentObject.static.candidateGroups
      }

      $scope.property.value = {}
      $scope.property.value.assignment = $scope.assignment
      $scope.updatePropertyInModel($scope.property)
      $scope.close()
    }

    // Close button handler
    $scope.close = function () {
      $scope.property.mode = 'read'
      $scope.$hide()
    }

    var handleAssignmentInput = function ($assignment) {
      function isEmptyString(value) {
        return value === undefined || value === null || value.trim().length === 0
      }

      if (isEmptyString($assignment.assignee)) {
        $assignment.assignee = undefined
      }
      var toRemoveIndexes
      var removedItems = 0
      var i = 0
      if ($assignment.candidateUsers) {
        toRemoveIndexes = []
        for (i = 0; i < $assignment.candidateUsers.length; i++) {
          if (isEmptyString($assignment.candidateUsers[i].value)) {
            toRemoveIndexes[toRemoveIndexes.length] = i
          }
        }

        if (toRemoveIndexes.length == $assignment.candidateUsers.length) {
          $assignment.candidateUsers = undefined
        } else {
          removedItems = 0
          for (i = 0; i < toRemoveIndexes.length; i++) {
            $assignment.candidateUsers.splice(toRemoveIndexes[i] - removedItems, 1)
            removedItems++
          }
        }
      }

      if ($assignment.candidateGroups) {
        toRemoveIndexes = []
        for (i = 0; i < $assignment.candidateGroups.length; i++) {
          if (isEmptyString($assignment.candidateGroups[i].value)) {
            toRemoveIndexes[toRemoveIndexes.length] = i
          }
        }

        if (toRemoveIndexes.length == $assignment.candidateGroups.length) {
          $assignment.candidateGroups = undefined
        } else {
          removedItems = 0
          for (i = 0; i < toRemoveIndexes.length; i++) {
            $assignment.candidateGroups.splice(toRemoveIndexes[i] - removedItems, 1)
            removedItems++
          }
        }
      }
    }

    function initStaticContextForEditing($scope) {
      if (
        !$scope.popup.assignmentObject.static.candidateUsers ||
        $scope.popup.assignmentObject.static.candidateUsers.length == 0
      ) {
        $scope.popup.assignmentObject.static.candidateUsers = [{ value: '' }]
      }
      if (
        !$scope.popup.assignmentObject.static.candidateGroups ||
        $scope.popup.assignmentObject.static.candidateGroups.length == 0
      ) {
        $scope.popup.assignmentObject.static.candidateGroups = [{ value: '' }]
      }
    }
  }
])
